#pragma once

#include <vector>
#include <Ogre.h>
#include <OIS/OIS.h>

#include "KeysState.h"

class IGameState;

//! This base class manages game states and receives and distributes input and 
//! frame events. It is heavily dependent on OIS and Ogre.
//! @remark This class does not take ownership of any state.
class BaseGameManager : 
	public Ogre::FrameListener, 
	public OIS::MouseListener,
	public OIS::KeyListener
{

protected:

	//! Input / Output variables
	//!
	OIS::Keyboard * mKeyboard;
	OIS::Mouse * mMouse;

	//! Render window.
	//! 
	Ogre::RenderWindow * mRenderWin;

	//! If it turns false, the application will end.
	//!
	bool mContinue;

	//! The current global state of the keys.
	//!
	KeysState mKeysState;

	//! A list of the currently active game states. Only the one at the vector::back() will receive
	//! input and frame events.
	//!
	std::vector<IGameState*> mStates;

public:

	//! Constructs a new GameManager object.
	//!
	//! @param win A valid pointer to the ogre RenderWindow.
	//! @param keyboard A valid pointer to the OIS::Keyboard.
	//! @param mouse A valid pointer to the OIS::Mouse
	//!
	BaseGameManager(Ogre::RenderWindow * win, OIS::Keyboard * keyboard, OIS::Mouse * mouse);

	//! Destroys the GameManager, among other things, calling the exit function of the active states.
	//!
	virtual ~BaseGameManager();

	//! Returns a const reference to the current KeysState.
	//!
	KeysState const & GetKeysState() const { return mKeysState; }


	/* MOUSE LISTENER */

	//! Receives an event when the mouse moves, forwarding the event to the main state.
	//!
	virtual bool mouseMoved(const OIS::MouseEvent &e);

	//! Receives an event when a mouse button is pressed, forwarding the event to the main state.
	//!
	virtual bool mousePressed(const OIS::MouseEvent &e, OIS::MouseButtonID id);

	//! Receives an event when a mouse button is released, forwarding the event to the main state.
	//!
	virtual bool mouseReleased(const OIS::MouseEvent &e, OIS::MouseButtonID id);


	/* KEY LISTENER */

	//! Receives an event when a key is pressed, forwarding the event to the main state.
	//!
	virtual bool keyPressed(const OIS::KeyEvent &e);

	//! Receives an event when a key is released, forwarding the event to the main state.
	//!
	virtual bool keyReleased(const OIS::KeyEvent &e);

	
	//! Receives an event when a new frameRendering is queued, forwarding the event to the main state.
	//!
	virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt);

	/* GAME STATES */

	//! Initializes the GameManager with a certain state.
	//! 
	virtual void Start(IGameState* state);


	//! Exits the current main state and adds the new one.
	//!
	virtual void ChangeState(IGameState* state);

	//! Pauses the current main state, and pushes a new state that becomes the main one.
	//!
	virtual void PushState(IGameState* state);

	//! Exits the current main state, resuming the previous one.
	//!
	virtual void PopState();

	//! Called to indicate that we should exit either the current state or the game.
	//!
	void ShouldExit(bool b);
};